﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Diagnostics;
using System.Xml.Linq;
using System.Web;
using System.IO;
using System.Configuration;
using System.Web.Security;
using Renci.SshNet;
using TireService.Data;
using System.Web.Hosting;

namespace TireService.Web
{
    public class InterfaceBLL
    {
        /// <summary>
        /// Interface function that read xml files and creates customers and customersubscriptions
        /// </summary>
        /// <param name="PartnerId">Id on partner to activate interface for</param>
        /// <param name="ImportDate">Date to import interface file for</param>
        public void GenerateCustomerAndSubscription(int PartnerId, DateTime ImportDate)
        {
            try
            {
                // Instatiate datalayer
                TireServiceDB db = new TireServiceDB();

                // Get partner
                PartnerListEDI partner = db.GetPartnerEDI(PartnerId);

                if (partner == null)
                {
                    // Error, partner not found
                    throw new ArgumentException("Partner not found");
                }

                if (partner.InActive)
                {
                    // Error, partner inactive
                    throw new ArgumentException("Partner is inactive");
                }

                // Load xml file
                XDocument interfaceXmlFile = new XDocument();

                // Prepare xml filename based on importdate
                string month = ImportDate.Month.ToString();
                if (month.Length == 1)
                {
                    month = "0" + month;
                }

                string day = ImportDate.Day.ToString();
                if (day.Length == 1)
                {
                    day = "0" + day;
                }
                string XMLFilename = partner.XMLInterfaceFileName + "_" + ImportDate.Year.ToString() + month + day + ".xml";

                //interfaceXmlFile = XDocument.Load(HttpContext.Current.Server.MapPath("App_Data\\" + XMLFilename));
                interfaceXmlFile = XDocument.Load(Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, "App_Data\\" + XMLFilename));

                // Read XML file into object
                var customers = from p in interfaceXmlFile.Elements("customer")
                                select new
                                {
                                    Name = p.Element("name").Value,
                                    Address = p.Element("address").Value,
                                    ZipCode = p.Element("zipcode").Value,
                                    City = p.Element("city").Value,
                                    Country = Convert.ToInt32(p.Element("country").Value),
                                    Phone = p.Element("phone").Value,
                                    Mobile = p.Element("mobile").Value,
                                    Email = p.Element("email").Value,
                                    Createdate = p.Element("createdate").Value,
                                    Quantity = p.Element("quantity").Value,
                                    SubscriptionId = p.Element("subscriptionid").Value,
                                    Price = p.Element("price").Value,
                                    Id = p.Element("orderid").Value
                                };

                if (PartnerId == 1)
                {
                    // HACK: Hardcode what subscription Benify is buying at Mobilhjulskift
                    string subscriptionid = "6";

                    // Partner is Benify - change customer source data (SubscriptionId is predefined to 6: BronzePlus Subscription, Yearly)
                    //customers = from p in interfaceXmlFile.Descendants("customer")
                    customers = from p in interfaceXmlFile.Elements("customer")
                               select new
                               {
                                   Name = p.Element("name").Value,
                                   Address = p.Element("address").Value,
                                   ZipCode = p.Element("zipcode").Value,
                                   City = p.Element("city").Value,
                                   Country = Convert.ToInt32(p.Element("country").Value),
                                   Phone = p.Element("phone").Value,
                                   Mobile = p.Element("mobile").Value,
                                   Email = p.Element("email").Value,
                                   Createdate = p.Element("createdate").Value,
                                   Quantity = p.Element("quantity").Value,
                                   SubscriptionId = subscriptionid,
                                   Price = db.GetPartnerSubscriptionPrice(PartnerId, Convert.ToInt32(subscriptionid)).ToString(),
                                   Id = p.Element("benifyid").Value // HACK: Different xml scheme for Benify xml
                               };
                }

                // Array for subscription interface log (1: OrderId, 2: Action and description (Invoiced, Failed))
                Dictionary<int, string> interface_log = new Dictionary<int, string>();

                // Instantiate email service
                EmailNotificationServices emailService = new EmailNotificationServices();

                // Instantiate e-conomic service
                EconomicInterface ecoInterface = new EconomicInterface();

                // Define system userid (Used for logging)
                Guid SystemUserId = new Guid(ConfigurationManager.AppSettings["SystemUserId"].ToString()); // System ID - Jannik79

                // Instantiate customer business logic
                CustomerBLL customerBLL = new CustomerBLL();

                // Initiate customer subscription business logic
                CustomerSubscriptionBLL customersubscriptionBLL = new CustomerSubscriptionBLL();

                // Read object
                foreach (var customer in customers)
                {
                    try
                    {                       
                        // Check that customer order has not already been processed
                        if (db.ExternalOrderInterfaces.SingleOrDefault(p => p.ExternalOrderId == customer.Id & p.SubscriptionId == Convert.ToInt32(customer.SubscriptionId)) != null)
                        {
                            // Create customer
                            Customer newcustomer = new Customer();
                            string phone1 = "";
                            string phone2 = "";
                            int phone1type = 0;
                            int? phone2type = null;

                            if (customer.Mobile != null & customer.Phone != null)
                            {
                                phone1 = customer.Phone;
                                phone1type = 1;
                                phone2 = customer.Mobile;
                                phone2type = 0;
                            }
                            else
                            {
                                if (customer.Mobile != null & customer.Phone == null)
                                {
                                    phone1 = customer.Mobile;
                                    phone1type = 0;
                                    phone2 = null;
                                    phone2type = null;
                                }
                                else
                                {
                                    if (customer.Mobile == null & customer.Phone != null)
                                    {
                                        phone1 = customer.Phone;
                                        phone1type = 1;
                                        phone2 = null;
                                        phone2type = null;
                                    }
                                    else
                                    {
                                        // Interface failed
                                        interface_log.Add(Convert.ToInt32(customer.Id), "Fejl: Ordre/Kunde kunne ikke oprettes via interface grundet invalide data");
                                    }
                                }
                            }

                            newcustomer = customerBLL.UpdateCustomer(db, newcustomer, 0, partner.ActAsParentCustomer, partner.CustomerId, partner.ParentPayInvoice, partner.IsCompany, null, null, customer.Name, customer.Address, customer.ZipCode, customer.City, customer.Country, customer.Address, customer.ZipCode, customer.City, phone1, phone1type, phone2, phone2type, customer.Email, true, partner.SyncToEconomic, partner.ManualInvoicing, partner.InvoicePBS, true);                            

                            // Get subscription 
                            Subscription subscription = db.GetSubscription(Convert.ToInt32(customer.SubscriptionId));

                            // Calculate subscription renew date
                            // Renewal dates: 01/03 and 01/09
                            DateTime LastRenewalDate = customersubscriptionBLL.CalculateLastRenewalDate(Convert.ToDateTime(DateTime.Now));
                            DateTime NextRenewalDate = customersubscriptionBLL.CalculateNextRenewalDate(LastRenewalDate, subscription);
                            decimal Price = Convert.ToDecimal(customer.Price); 
                            bool BalancingIncluded = subscription.BalancingIncluded;

                            // Create customersubscription
                            CustomerSubscription customersubscription = new CustomerSubscription();
                            customersubscriptionBLL.UpdateCustomerSubscription(db, customersubscription, newcustomer, 0, subscription.SubscriptionId, LastRenewalDate, NextRenewalDate, false, BalancingIncluded, Price, SystemUserId, true, "Bestilling af abonnement og bil");

                            // Mark in external interface table that customer has been processed
                            ExternalOrderInterface externalorder = new ExternalOrderInterface();
                            externalorder.PartnerId = PartnerId;
                            externalorder.ExternalOrderId = customer.Id;
                            externalorder.Quantity = Convert.ToInt32(customer.Quantity);
                            externalorder.SubscriptionId = Convert.ToInt32(customer.SubscriptionId);

                            newcustomer.ExternalOrderInterfaces.Add(externalorder);

                            db.ExternalOrderInterfaces.InsertOnSubmit(externalorder);

                            // Submit to database
                            db.SubmitChanges();

                            // TODO: 31-05-2013 - Below code can be made if customer can place ordre on more subscriptions that are also different
                            //// Check if more orders on same customer
                            //if (customers.Count(p => p.Id == customer.Id) > 1)
                            //{
                            //    // More ordres exists on customer - add one more interface record
                            //    var customer2 = customers.SingleOrDefault(p => p.Id == customer.Id
                            //}

                            // Sync customer with E-conomic
                            // Create debtor in E-conomic
                            ecoInterface.CreateDebtor(newcustomer, db);

                            // Log creation
                            interface_log.Add(Convert.ToInt32(customer.Id), "OK: Kunde/ordre importeret via interface");

                            // Send email to customer with finalise signup link
                            emailService.Interface_FinaliseSignUp_SendCustomerEmail(newcustomer.Email, newcustomer.Name, newcustomer.CustomerId);
                        }
                    }
                    catch (Exception ex)
                    {
                        // TODO: Create log on exception
                        // Interface failed
                        interface_log.Add(0, "Fejl: Interface fejlede med følgende besked: " + ex.Message);
                    }
                }

                // Return log on interface to finance email
                string logHTML = "<b>Interface oversigt</b><br><table><tr><td>Ordre/Kundeid</td><td>Status og handling</td></tr>";
                foreach (KeyValuePair<int, string> log in interface_log)
                {
                    logHTML += "<tr><td>" + log.Key.ToString() + "</td><td>" + log.Value + "</td></tr>";
                }
                logHTML += "</table>";

                string Subject = "Interface overførsler";
                emailService.SendFinanceInternalEmailNotification(Subject, logHTML);

                // Dispose database connection
                db.Dispose();
            }
            catch (Exception ex)
            {
                Shared email = new Shared();
                email.SendEmail("jannik@mobilhjulskift.dk", "system@mobilhjulskift.dk", ex.Message, "Oprettelse af Benify kunder fejlede", true, false, null, null, null);
            }
            
        }

        public bool CopyOrderXMLFileFromPartnerSFTP(PartnerListEDI partner, string SourceFilename, string DownLoadFileName) 
        {
            try
            {
                //string folder = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, "App_Data\\" + DownLoadFileName);
                //string folder = Server.MapPath("App_Data\\" + DownLoadFileName); // HttpContext.Current.Server.MapPath("App_Data\\" + DownLoadFileName);
                //string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DownLoadFileName);
                string folder = HostingEnvironment.MapPath(@"~/App_Data/" + DownLoadFileName);

                Shared email = new Shared();
                email.SendEmail("jannik@mobilhjulskift.dk", "system@mobilhjulskift.dk", folder, "Folder sat", true, false, null, null, null);
                //string folder = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, "Interfaces\\Data\\" + DownLoadFileName);

                var con = new ConnectionInfo(partner.ServerLink, partner.Username, new PasswordAuthenticationMethod(partner.Username, partner.Password));
                using (var client = new SftpClient(con))
                {
                    client.Connect();

                    using (var fs = new FileStream(folder, FileMode.Create))
                    {
                        client.DownloadFile("/" + SourceFilename, fs);
                        fs.Close();
                    }

                    client.Disconnect();
                }
            }
            catch (Exception ex)
            {
                Shared email = new Shared();
                email.SendEmail("jannik@mobilhjulskift.dk", "system@mobilhjulskift.dk", ex.Message, "SFTP Interface fil download fejlede", true, false, null, null, null);
                return false;
            }

            return true;
        }

        //public bool CopyOrderXMLfileFromBenify(Uri serverUri, string BenifyUserName, string BenifyPassword)
        //{
        //    // The serverUri parameter should start with the ftp:// scheme. 
        //    if (serverUri.Scheme != Uri.UriSchemeFtp)
        //    {
        //        return false;
        //    }

        //    // Get the object used to communicate with the server.
        //    WebClient request = new WebClient();

        //    // Login to FTP
        //    request.Credentials = new NetworkCredential(BenifyUserName, BenifyPassword);
        //    try
        //    {
        //        // Download file from FTP
        //        byte[] newFileData = request.DownloadData(serverUri.ToString());
        //        string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
        //        //Debug.WriteLine(fileString);

        //        // Save file to other location
        //        string folder = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, "Interfaces\\Data\\Benify.xml");
        //        using (FileStream fs = File.Create(folder, 1024))
        //        {
        //            Byte[] info = new UTF8Encoding(true).GetBytes(fileString);
        //            // Add some information to the file.
        //            fs.Write(info, 0, info.Length);
        //        }
        //    }
        //    catch (WebException e)
        //    {
        //        Debug.WriteLine(e.ToString());
        //    }
        //    return true;

        //}

    }
}
